package pcloud.client.scheduler;

import java.lang.Thread.State;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

import pcloud.client.util.FileResourceInfo;
import pcloud.client.util.Logger;
import pcloud.client.worker.CloudTask;

public class TaskScheduler implements Runnable
{
	private Queue<CloudTask> waitingQueue = new LinkedList<CloudTask>();
	private Map<String, CloudTask> blockingIndex = new HashMap<String, CloudTask>();;

	Thread shcedulerThread;
	volatile boolean schedulerOn;

	public Thread getWorkingThread()
	{
		return shcedulerThread;
	}

	public TaskScheduler()
	{
		shcedulerThread = new Thread(this);
	}

	public void start()
	{
		schedulerOn = true;
		State state = shcedulerThread.getState();
		logger.info("Task scheduler starting, current state: " + state);
		if (state.equals(State.TERMINATED) || state.equals(State.NEW)) {
			shcedulerThread.start();
		}
	}

	public void stop()
	{
		schedulerOn = false;

	}

	public boolean add(CloudTask cloudTask)
	{
		if (cloudTask == null) {
			logger.info("Task not added: empty task!");
			return false;
		}

		FileResourceInfo fileInfo = cloudTask.getFileInfo();
		String path = fileInfo.getFullPath();

		// 对于正在锁定的文件, 暂时不受理
		synchronized (blockingIndex) {
			if (blockingIndex.containsKey(path)) {
				logger.info("Task not added: a task is blocking file: "
						+ cloudTask.toString());
				return false;
			}
		}

		synchronized (waitingQueue) {
			waitingQueue.offer(cloudTask);
		}
		logger.info("Task added: " + cloudTask.toString());
		return true;
	}

	public void run()
	{
		logger.info("handleTask thread started!");
		while (schedulerOn) {
			try {
				runTask();
			} catch (Exception e) {
				logger.info("handleTask failed!"+e.getMessage());
			}
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		logger.info("handleTask thread ended!");
	}

	private void runTask()
	{
		CloudTask cloudTask;
		synchronized (waitingQueue) {
			cloudTask = waitingQueue.poll();
			if (cloudTask == null) {
				return;
			}
		}
		logger.info("Scheduller polled one task: " + cloudTask.toString());

		String blockingFilePath = blockFile(cloudTask);
		cloudTask.doWorkWithTriggers();
		unblockFile(blockingFilePath);
		logger.info("Task handled: " + cloudTask.toString());
	}

	private String blockFile(CloudTask cloudTask)
	{
		synchronized (blockingIndex) {
			String blockingFile = cloudTask.getBlockingFile();
			if (blockingFile != null) {
				blockingIndex.put(blockingFile, cloudTask);
				return blockingFile;
			}
		}
		return null;
	}

	private CloudTask unblockFile(String blockingFilePath)
	{
		synchronized (blockingIndex) {
			return blockingIndex.remove(blockingFilePath);
		}
	}

}
